<script setup lang="ts">
import { ref, watch } from 'vue';
import type { UploaderFileListItem } from 'vant';
import { showToast } from 'vant';
import uploadImage from '@/utils/uploadImage';

const props = withDefaults(
  defineProps<{
    modelValue: string;
    maxCount?: number;
    fileType?: string[];
    label: string;
    name: string;
  }>(),
  {
    modelValue: '',
    maxCount: 1,
    fileType: () => ['image/jpeg', 'image/png', 'image/gif'],
    label: '',
    name: '',
  }
);

const emit = defineEmits<{
  (e: 'update:modelValue', value: string): void;
}>();

const fileList = ref<UploaderFileListItem[]>([]);

watch(
  () => props.modelValue,
  () => {
    if (props.modelValue) {
      fileList.value = props.modelValue.split(',').map((url, index) => {
        return {
          ...(fileList.value[index] || {}),
          url,
        };
      });
    } else {
      fileList.value = [];
    }
  },
  {
    immediate: true,
  }
);

// 上传前置处理
const beforeRead = (file: any) => {
  if (!props.fileType.includes(file.type)) {
    showToast('请上传图片文件');
    return false;
  }
  return true;
};

// 上传后置处理
const afterRead = async (fileListItems: UploaderFileListItem | UploaderFileListItem[]) => {
  const fileListItem = Array.isArray(fileListItems) ? fileListItems[0] : fileListItems;
  try {
    fileListItem.status = 'uploading';
    fileListItem.message = '上传中...';
    if (fileListItem.file) {
      const res = await uploadImage(fileListItem.file);
      fileListItem.url = res?.data.url;
      fileListItem.status = 'done';
      fileListItem.message = '';
      emit('update:modelValue', fileList.value.map((v) => v.url).join(','));
    }
  } catch (err) {
    console.error(err);
    fileListItem.status = 'failed';
    fileListItem.message = '上传失败';
  }
};

// 删除前置处理
const beforeDelete = (item: UploaderFileListItem, param: { index: number; name: string }) => {
  emit(
    'update:modelValue',
    fileList.value
      .filter((v, i) => i !== param.index)
      .map((v) => v.url)
      .join(',')
  );
  return true;
};

// 文件大小超过限制时触发
const onOversize = () => {
  showToast('文件大小不能超过 4M');
};
</script>
<template>
  <van-field :name="name" :label="label">
    <template #input>
      <van-uploader
        v-model="fileList"
        multiple
        :max-size="4000 * 1024"
        @oversize="onOversize"
        :max-count="maxCount"
        :before-read="beforeRead"
        :after-read="afterRead"
        :before-delete="beforeDelete"
      />
    </template>
  </van-field>
</template>
<style lang="less" scoped></style>
